
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Arizona State University
//  All rights reserved.
//  BSD License: http://www.opensource.org/licenses/bsd-license.html
//  Author(s): Adam Kubach
//
///////////////////////////////////////////////////////////////////////////////

#include "VRV/Core/BaseApplication.h"
#include "VRV/Core/JugglerFunctors.h"
#include "VRV/Core/Exceptions.h"

#include "Usul/App/Application.h"
#include "Usul/Functions/SafeCall.h"
#include "Usul/Strings/Format.h"
#include "Usul/User/Directory.h"

#include "vrj/Kernel/Kernel.h"

#include "boost/bind.hpp"

using namespace VRV::Core;


///////////////////////////////////////////////////////////////////////////////
//
//  Constructor.
//
///////////////////////////////////////////////////////////////////////////////

BaseApplication::BaseApplication() : 
  BaseClass ( vrj::Kernel::instance() ),
  _mutex()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Destructor.
//
///////////////////////////////////////////////////////////////////////////////

BaseApplication::~BaseApplication()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Run the application.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::run()
{
  // Get the kernel.
  vrj::Kernel* kernel ( vrj::Kernel::instance() );

  // Tell the kernel that we are the app.
  kernel->setApplication ( this );

  // Start the kernel.
  kernel->start();

  // Wait for events.
  kernel->waitForKernelStop();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Quit the application.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::quit()
{
  vrj::Kernel::instance()->stop();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Initialize this instance.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::init()
{
  bool stop ( false );

  try
  {
    BaseClass::init();
    this->_init();
  }

  catch ( const std::exception &e )
  {
    std::cout << "Error 1082603967: "
              << "Exception generated while initializing."
              << "\n\tWhat: " << e.what()
              << std::endl;
    stop = true;
  }
  catch ( ... )
  {
    std::cout << "Error 1082603859: "
              << "Unknown exception generated while initializing." 
              << std::endl;
    stop = true;
  }

  // Are you supposed to stop?
  if ( stop )
    vrj::Kernel::instance()->stop();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Initialize the application.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_init()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called before the frame.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::preFrame()
{
  BaseClass::preFrame();
  Usul::Functions::safeCall ( boost::bind ( &BaseApplication::_preFrame, this ), "3669056808" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called before the frame.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_preFrame()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called after preFrame, but before the frame.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::latePreFrame()
{
  BaseClass::latePreFrame();
  Usul::Functions::safeCall ( boost::bind ( &BaseApplication::_latePreFrame, this ), "1897051329" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called after preFrame, but before the frame.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_latePreFrame()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called when the frame is done.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::postFrame()
{
  BaseClass::postFrame();
  Usul::Functions::safeCall ( boost::bind ( &BaseApplication::_postFrame, this ), "2751540437" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Called when the frame is done.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_postFrame()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the default configuration filename path.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_setDefaultPath ( std::string& filename, const std::string& name )
{
  // Get the vendor and the program.
  const std::string vendor  ( Usul::App::Application::instance().vendor()  );
  const std::string program ( Usul::App::Application::instance().program() );

  // Set default file path.
  filename = Usul::Strings::format ( Usul::User::Directory::program ( vendor, program ), "/", name, ".xml" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Load all the config files.
//
///////////////////////////////////////////////////////////////////////////////

void BaseApplication::_loadConfigFiles ( const std::vector < std::string > &configs )
{
  // Load the config files.
  std::for_each ( configs.begin(), configs.end(), VRV::Core::Detail::LoadConfigFile() );
}
